package com.example.hdfs;

/**
 * Created with IntelliJ IDEA.
 * ClassName: HdfsClient
 * Package: com.example.hdfs
 * Description:
 * User: fzykd
 *
 * @Author: LQH
 * Date: 2023-07-14
 * Time: 13:13
 */


import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;

/**
 * 客户端代码常用套路
 * 1.获取一个客户端对象
 * 2.执行相关的操作命名
 * 3.关闭资源
 * HDFS zookeeper
 */

public class HdfsClient {

    //快捷键 Ctrl + Alt + f 生成全局变量
    private FileSystem fs;


    @Before
    //在执行之前执行
    //封装重复的操作
    public void init() throws URISyntaxException, IOException, InterruptedException {
        //连接集群的nn地址 hdfs协议
        //客户端和NameNode交互 内部的通信协议是8020 页面访问是9870
        URI uri = new URI("hdfs://hadoop102:8020");

        //创建一个配置文件
        Configuration configuration = new Configuration();

        configuration.set("dfs.replication", "2");

        //用户 不然没有访问权限
        String user = "bobo";

        //获取到客户端对象
        fs = FileSystem.get(uri, configuration, user);
    }

    @After
    //执行之后执行
    public void close() throws IOException {
        //关闭资源
        fs.close();
    }


    //创建目录
    @Test
    public void testMkdir() throws URISyntaxException, IOException, InterruptedException {
        //执行操作 创建文件夹
        fs.mkdirs(new Path("/xiyou/huaguoshan"));
    }

    //上传文件

    /**
     * 参数优先级
     * hdfs-default.xml => hdfs-site.xml => 在项目资源目录下的配置文件优先级高 => 代码配置
     *
     * @throws IOException
     */
    @Test
    public void testPut() throws IOException {
        //参数1.删除原始数据
        //2.是否允许覆盖
        //3.原数据路径
        //4.目的地路径
        fs.copyFromLocalFile(false, true, new Path("d:/sunwukong.txt"), new Path("/xiyou/huaguoshan"));
    }


    //文件下载
    @Test
    public void testGet() throws IOException {
        //参数说明
        //1.下载的原文件是否删除
        //2.HDFS的原文件路径
        //3.目标地址 要下载的路径
        //4.是否开启本地文件校验
        fs.copyToLocalFile(false, new Path("hdfs://hadoop102/xiyou/huaguoshan"), new Path("d:/"), false);
    }


    //删除文件
    @Test
    public void testRm() throws IOException {
        //参数说明
        //1.要删除的路径
        //2.是否递归删除
        fs.delete(new Path("/jdk-8u212-linux-x64.tar.gz"), false);

        //删除空目录
        fs.delete(new Path("/xiyou"), false);

        //删除非空目录
        fs.delete(new Path("/jinguo"), true);

    }

    //文件的更名和移动
    @Test
    public void testmv() throws IOException {
        //参数说明
        //1.原文件路径
        //2.目标文件路径
        //修改文件名称
        fs.rename(new Path("/wcinput/word.txt"), new Path("/wcinput/ss.txt"));

        //文件移动和更名 移动话原文件不存在
        fs.rename(new Path("/wcinput/ss.txt"), new Path("/cls.txt"));

        //目录的更名
        fs.rename(new Path("/wcinput"), new Path("/iii"));
    }

    //获取文件详情
    @Test
    public void fileDetail() throws IOException {
        //1.哪一个路径的信息
        //2.一个是递归

        //获取文件信息
        RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);

        //返回的是一个迭代器 一个遍历出来
        while (listFiles.hasNext()) {
            LocatedFileStatus next = listFiles.next();
            System.out.println("========" + next.getPath() + "=======");
            System.out.println(next.getPermission());
            System.out.println(next.getOwner());
            System.out.println(next.getGroup());
            System.out.println(next.getLen());
            System.out.println(next.getModificationTime());
            System.out.println(next.getReplication());
            System.out.println(next.getBlockSize());
            System.out.println(next.getPath().getName());
            //获取块信息
            BlockLocation[] blockLocations = next.getBlockLocations();

            System.out.println(Arrays.toString(blockLocations));
        }
    }

    //判断是文件或者文件夹
    @Test
    public void testFile() throws IOException {
        FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
        //判断根目录下哪些是文件 哪些是目录
        for (FileStatus status : fileStatuses){
            if (status.isFile()){
                System.out.println("文件: " +  status.getPath().getName());
            }else {
                System.out.println("目录: " + status.getPath().getName());
            }
        }
    }



}
